package top.itbook.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;

/**
 * 其实SHA-1单向散列函数也不安全了，具体可参考Google宣告攻破SHA-1
 * 但相比于MD5，还是有着更高的安全性。虽然还是没有逃过被碰撞的魔爪就是了 -.-
 */
public class SHA1 extends Provider {
    private static SHA1 instance; // 本类对象
    final private static String salt = "@KingSHA1.top"; // 盐值

    /**
     * 构造器
     * @param name 提供者名称
     * @param versionStr 算法版本
     * @param info 算法信息
     */
    private SHA1(String name,String versionStr,String info){
        super(name,versionStr,info); // 调用父类构造器
    }

    /**
     * 返回本类实例化对象
     * 懒汉单例的设计模式
     * @return SHA-1 哈希加密算法对象
     */
    public static SHA1 getInstance(){
        if (instance == null){
            instance = new SHA1("King","0.2","SHA-1信息摘要加密算法，采用强化的设计方式，以防止通过彩虹表轻松破解");
        }
        return instance;
    }

    /**
     * SHA - 1 信息摘要算法 - 不可逆加密 - 字符串加密
     * @param content 要获取摘要的字符串
     * @return 若成功获取摘要则返回十六进制字符串，若方法发生不可预见的错误导致方法中止则返回null
     */
    public String SHA1encryption(String content){
        MessageDigest messageDigest;
        String s = null; // 加密后的字符串
        try {
            messageDigest = MessageDigest.getInstance("SHA-1"); // 获取实例化对象
            // 进行加盐处理（也就是强行拼接一下字符串）
            content = content + salt;
            // 更新摘要
            messageDigest.update(content.getBytes());
            // 获取数据的信息摘要 - 进行哈希计算
            byte[] resultBytes = messageDigest.digest();
            // 将信息转换为十六进制字符串
            s = convertString(resultBytes);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return s;
    }

    // 将字节数组转换为十六进制字符串 - 此方法为工具方法，切勿反射获取
    private String convertString(byte[] bytes){
        StringBuilder stringBuilder = new StringBuilder(bytes.length * 2);
        // 使用string的format方法进行转换
        for (byte aByte : bytes) {
            stringBuilder.append(String.format("%02x",aByte & 0xff));
        }
        return stringBuilder.toString();
    }
}
